import { MysqlConn, toWhere } from "./base";
import { Util } from "../lib/Util";

class List<T>{
    private mydb: MysqlConn
    private table: string
    private findKey: { [x: string]: any }
    private _data: T[] = []
    constructor(db: MysqlConn, table: string, findKey: { [x: string]: any }) {
        this.mydb = db
        this.table = table;
        this.findKey = findKey;
    }

    get data() {
        return this._data as T[]
    }

    get length() {
        return this._data.length
    }

    // 深拷贝一份数据
    clone() {
        return Util.copy(this._data) as T[];
    }

    private _start = 0;
    private _limit = 0;
    limit(num: number) {
        this._limit = num;
        return this;
    }
    skip(num: number) {
        this._start = num;
        return this;
    }

    get_at(index: number, org: boolean = false) {
        if (index < 0 || index >= this._data.length)
            return null;
        if (org)
            return this._data[index];
        return Util.copy(this._data[index]) as T;
    }

    async rm_at(index: number) {
        if (index < 0 || index >= this._data.length)
            return;
        var rp: any = this._data.splice(index, 1);
        for (var i = 0; i < rp.length; i++) {
            await this.mydb.deleteOnce(this.table, rp)
        }

        return;
    }

    async clear_all() {
        while (this.length > 0) {
            await this.rm_at(0);
        }
    }

    private _has_same(v: T | any, fobj: any) {
        var bSame = true;
        for (var key in fobj) {
            if (v[key] != fobj[key]) {
                bSame = false;
                break;
            }
        }
        return bSame;
    }

    del(fObj: any) {
        var idx = -1;
        for (var i = 0; i < this._data.length; i++) {
            var c = this._data[i];
            if (this._has_same(c, fObj)) {
                idx = i;
                break;
            }
        }
        // var idx = this._data_.indexOf(v);
        if (idx >= 0)
            this.rm_at(idx);
    }

    async load(filter?: { [key: string]: 0 | 1 }, sort?: { [key: string]: -1 | 1 }) {
        try {
            let show: string[] = []
            filter = filter || {}
            let keys = Object.keys(filter)
            if (keys.length > 0) {
                if (filter[keys[0]] == 0) {
                    // 这里是屏蔽模式
                    let listInfo = this.mydb.tableFields[this.table];
                    if (listInfo) for (let key in listInfo) if (filter[key] == undefined) show.push(key)
                }
                else {
                    show = keys;
                }
            }

            let qStr = `select ${show.length == 0 ? '*' : show.join(',')} from ${this.table} `;
            if (Object.keys(this.findKey).length > 0) {
                qStr += `where ${toWhere(this.findKey)}`
            }

            if (sort) {
                let str = " order by "
                for (let key in sort) {
                    str += ` ${key} ${(sort[key] == -1) ? "Desc" : ""}`
                }

                qStr += str;
            }

            if (this._limit != 0 && this._start != 0) {
                qStr += ` limit ${this._start},${this._limit}`
            }
            else if (this._limit != 0) {
                qStr += ` limit ${this._limit}`
            }
            else if (this._start != 0) {
                qStr += ` limit ${this._start},-1`
            }

            let list = await this.mydb.query<T>(qStr)
            if (list.length > 0) {
                this._data = list
            }
            else {
                this._data = []
            }
        }
        catch (e) {
            throw e
        }

        return this;
    }

    async insert(info: { [x: string]: any }) {
        let result = await this.mydb.insert(this.table, info)
        this._data.push(info as T);
        return result;
    }

}

export function GetList<T>(db: MysqlConn, table: string, findKey: { [x: string]: any }) {
    return new List<T>(db, table, findKey)
}